package com.lin.gulimall.search.thread;

import java.util.concurrent.*;

public class ThreadTest {
    //当前系统线程池只有一两个，每个异步任务，提交给线程池，让他自己去执行
    public static ExecutorService service = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start...");
//        CompletableFuture.runAsync(()->{
//            System.out.println("当前线程"+Thread.currentThread().getId());
//            int i = 10/2;
//            System.out.println("运行结果"+i);
//        },service);

//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程" + Thread.currentThread().getId());
//            int i = 10 / 0;
//            System.out.println("运行结果" + i);
//            return i;
//        }, service).whenComplete((result,excption)->{
//            //虽然能得到异常信息，但是没法修改返回数据
//            System.out.println("异步任务成功完成了...结果是:"+result+";异常是:"+excption);
//            //能感知异常，同时能返回默认值。
//        }).exceptionally(throwable -> 10);

        //方法执行完成后的处理，无论是成功还是失败。
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程" + Thread.currentThread().getId());
//            int i = 10 / 0;
//            System.out.println("运行结果" + i);
//            return i;
//        }, service).handle((res,thr)->{
//            if (res!=null){
//                return res*2;
//            }
//            if (thr!=null){
//                return 0;
//            }
//            return 0;
//        });
//        .thenRunAsync(() -> {
//            System.out.println("任务2启动了...");
//        }, service);
//          .thenAcceptAsync(res->{
//            System.out.println("任务2启动了...");
//          },service);
//        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程" + Thread.currentThread().getId());
//            int i = 10 / 4;
//            System.out.println("运行结果" + i);
//            return i;
//        }, service).thenApplyAsync(res -> {
//            System.out.println("任务2启动了...");
//            return "Hello" + res;
//        }, service);
//        System.out.println("main....end..."+future.get());

//        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务1线程" + Thread.currentThread().getId());
//            int i = 10 / 4;
//            System.out.println("任务1结束");
//            return i;
//        }, service);
//
//        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务2线程" + Thread.currentThread().getId());
//            try {
//                Thread.sleep(30000);
//                System.out.println("任务2结束");
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            return "Hello";
//        }, service);

//        future01.runAfterBothAsync(future02,()->{
//            System.out.println("任务3开始");
//        },service);

        //void accept(T t, U u);
//        future01.thenAcceptBothAsync(future02,(f1,f2)->{
//            System.out.println("任务3开始，之前的结果:"+f1+"-->"+f2);
//        },service);

        //R apply(T t, U u);
//        CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
//            return f1 + ":" + f2 + "->hello";
//        }, service);
//        System.out.println("main....end..."+future.get());

//        future01.runAfterEitherAsync(future02,()->{
//            System.out.println("任务3开始了");
//        },service);

        // void accept(T t);
//        future01.acceptEitherAsync(future02,(res)->{
//            System.out.println("任务3开始。。之前的结果："+res);
//        },service);

//        CompletableFuture<String> future = future01.applyToEitherAsync(future02, (res) -> {
//            System.out.println("任务3开始...之前的结果:" + res);
//            return res.toString() + "->哈哈";
//        }, service);


        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询图片的信息");
            return "hello.jpg";
        },service);

        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的属性");
            return "黑色+256g";
        },service);

        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品介绍");
            try {
                Thread.sleep(30000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "华为";
        },service);

//        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);
//        allOf.get(); //等待所有结果完成
//
//        System.out.println("main...end...."+futureImg.get()+futureAttr.get()+futureDesc.get());

        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureAttr, futureDesc);
        anyOf.get(); //等待所有结果完成

        System.out.println("main...end...."+anyOf.get());

    }


    public  void Thread01(String[] args) throws ExecutionException, InterruptedException {

        System.out.println("main....start...");
        /*
         * 1）、继承Thread
         * Thread thread = new Thread01();
         * thread.start();
         * System.out.println("main....end...");
         * 2）、实现Runnable接口
         * Runnable1 runnable1 = new Runnable1();
         * new Thread(runnable1).start();
         * System.out.println("main....end...");
         * 3）、实现Callable接口 +futureTask（可以拿到返回结果，可以处理异常）
         * FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
         * new Thread(futureTask).start();
         * Integer integer = futureTask.get();
         * System.out.println("main....end..."+integer);
         *
         * ***********以上三种启动线程的方式都不用。
         * 4）、线程池(ExecutorService)
         * 给线程池直接提交任务。
         * ervice.execute(new Runnable1());
         * 1、创建
         *   1)、Executors
         *   2)、ThreadPoolExecutor
         *
         *  future:可以获取到异步结果。
         *
         * 区别：
         *    1、2不能得到返回值，3可以得到返回值
         *    1、2、3都不能控制资源。
         *    4可以控制资源，性能稳定
         */


        /*
        * 七大参数
        * corePoolSize:[5] 核心线程数[一直存在，除非（allowCoreThreadTimeOut）]：线程池，创建好以后就准备就绪的线程数量，就等待来接受异步任务去执行。
        *       5个  Thread thread = new Thread(); thread.start();
        * maximumPoolSize: 最大线程数量。 控制资源
        * keepAliveTime: 存活时间。如果当前线程数量大于核心数量，只要线程空闲大于指定的空闲时间keepAliveTime，释放空闲的线程（maximumPoolSize-corePoolSize）
        * TimeUnit unit: 时间单位，
        * BlockingQueue<Runnable> workQueue: 阻塞队列，如果任务有很多，就会将目前多的任务放在队列里面，只要有线程空闲了，就会去队列里面取出任务执行。
        * ThreadFactory threadFactory: 线程的创建工厂。
        * RejectedExecutionHandler handler: 如果队列满了，按照指定的拒绝策略拒绝执行任务。
        *
        * 工作顺序：
        * 1、线程池创建，准备好core数量的核心线程，准备接受任务。
        *   1.1、core满了，就将再进来的任务放在阻塞队列中，空闲的core就会自己去阻塞队列获取任务执行。
        *   1.2、如果阻塞队列满了，就直接开启新线程执行，最大只能开到max指定的数量。
        *   1.3、如果max已经满了，但还有任务，就会开启拒绝策略。
        *   1.4、如果没有任务了，线程空闲了，当超过keepAliveTime时，就会自动释放，只剩下核心线程。
        *
        *       new LinkedBlockingDeque<>(),默认时Integer的最大值。
        *
        * 一个线程池 core 7   max 20   queue 50 ，100个并发进来
        * 7个会立即执行，然后50个进入queue，然后再开启13个线程。剩下30个就使用拒绝策略
        * 如果不想抛弃还要执行。CallerRunsPolicy;
        *
        */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        //Executors.newCachedThreadPool(); //core是0，所有都可以回收的。
        //Executors.newFixedThreadPool(5); //固定大小,核心等于最大的，都不可回收。
        //Executors.newScheduledThreadPool(); //定时任务的线程池
        //Executors.newSingleThreadExecutor(); //单线程的线程池，后台从队列里面获取任务，挨个执行。
        System.out.println("main....end...");

    }


    public static class Thread01 extends Thread{

        public void run(){
            System.out.println("当前线程"+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果"+i);
        }

    }

    public static class Runnable1 implements Runnable{

        @Override
        public void run() {
            System.out.println("当前线程"+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果"+i);
        }
    }

    public static class Callable01 implements Callable<Integer>{

        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程"+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果"+i);
            return i;
        }
    }
}
